#pragma once

#include <vector>
#include <string>
#include "enum.h"
using namespace std;

#include <boost/lexical_cast.hpp>

class Variable
{
private:
	string name;
	Parameter type;
	string value;

public:
	Variable(){};
	Variable(string s){this->name = s;};
	Variable(string s, Parameter p, string v){this->name = s;this->type = p;this->value = v;};
	string get_name(){return this->name;};
	Parameter get_typ(){return this->type;};
	void set_name(string s){this->name = s;};
	void set_type(Parameter p){this->type = p;};
	void set_value(string val){this->value = val;};
	string get_value(){return this->value;};
	bool is_empty(){return value.empty() ? true : false;}; // if(value.empty()) return true; else return false;

	Variable operator+(Variable v)
	{
		if(this->type == v.get_typ() || this->type == NATURALS && v.get_typ() == INTEGER || this->type == INTEGER &&  v.get_typ() == NATURALS)
		{
			switch (this->type)
			{
			case STRING:
				this->value = this->value + v.get_value();
				break;
			case CHAR:
				this->value = boost::lexical_cast<string>(  this->value.at(0) + v.get_value().at(0) );
				break;
			case INTEGER:
				this->value = boost::lexical_cast<string>(atoi(this->value.c_str()) + atoi(v.get_value().c_str()));
				break;
			case NATURALS:
				this->value = boost::lexical_cast<string>( (unsigned int) atoi(this->value.c_str()) + (unsigned int) atoi(v.get_value().c_str()));
				break;
			case BOOL:
				//ERROR ?
				break;
			}
		}
		return *this;
	};

	Variable operator-(Variable v)
	{
		if(this->type == v.get_typ() || this->type == NATURALS && v.get_typ() == INTEGER || this->type == INTEGER &&  v.get_typ() == NATURALS)
		{
			switch (this->type)
			{
			case STRING:
				//ERROR ?
				break;
			case CHAR:
				this->value = boost::lexical_cast<string>(  this->value.at(0) - v.get_value().at(0) );
				break;
			case INTEGER:
				this->value = boost::lexical_cast<string>(atoi(this->value.c_str()) - atoi(v.get_value().c_str()));
				break;
			case NATURALS:
				this->value = boost::lexical_cast<string>( (unsigned int) atoi(this->value.c_str()) - (unsigned int) atoi(v.get_value().c_str()));
				break;
			case BOOL:
				//ERROR ?
				break;
			}
		}
		return *this;
	};

	Variable operator*(Variable v)
	{
		if(this->type == v.get_typ() || this->type == NATURALS && v.get_typ() == INTEGER || this->type == INTEGER &&  v.get_typ() == NATURALS)
		{
			switch (this->type)
			{
			case STRING:
				//ERROR ?
				break;
			case CHAR:
				this->value = boost::lexical_cast<string>(  this->value.at(0) * v.get_value().at(0) );
				break;
			case INTEGER:
				this->value = boost::lexical_cast<string>( atoi(this->value.c_str()) * atoi(v.get_value().c_str()) );
				break;
			case NATURALS:
				this->value = boost::lexical_cast<string>( (unsigned int) atoi(this->value.c_str()) * (unsigned int) atoi(v.get_value().c_str()));
				break;
			case BOOL:
				//ERROR ?
				break;
			}
		}
		return *this;
	};

	Variable operator/(Variable v)
	{
		if(this->type == v.get_typ() || this->type == NATURALS && v.get_typ() == INTEGER || this->type == INTEGER &&  v.get_typ() == NATURALS)
		{
			switch (this->type)
			{
			case STRING:
				//ERROR ?
				break;
			case CHAR:
				this->value = boost::lexical_cast<string>(  this->value.at(0) / v.get_value().at(0) );
				break;
			case INTEGER:
				this->value = boost::lexical_cast<string>(atoi(this->value.c_str()) / atoi(v.get_value().c_str()));
				break;
			case NATURALS:
				this->value = boost::lexical_cast<string>( (unsigned int) atoi(this->value.c_str()) / (unsigned int) atoi(v.get_value().c_str()));
				break;
			case BOOL:
				//ERROR ?
				break;
			}
		}
		return *this;
	};

};